home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / utilities / text / less-278.lha / less-278 / src.lha / source / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-01  |  6.6 KB  |  311 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * High level routines dealing with getting lines of input 
  30.  * from the file being viewed.
  31.  *
  32.  * When we speak of "lines" here, we mean PRINTABLE lines;
  33.  * lines processed with respect to the screen width.
  34.  * We use the term "raw line" to refer to lines simply
  35.  * delimited by newlines; not processed with respect to screen width.
  36.  */
  37.  
  38. #include "less.h"
  39.  
  40. extern int squeeze;
  41. extern int chopline;
  42. extern int sigs;
  43. #if HILITE_SEARCH
  44. extern int hilite_search;
  45. extern int size_linebuf;
  46. #endif
  47.  
  48. /*
  49.  * Get the next line.
  50.  * A "current" position is passed and a "new" position is returned.
  51.  * The current position is the position of the first character of
  52.  * a line.  The new position is the position of the first character
  53.  * of the NEXT line.  The line obtained is the line starting at curr_pos.
  54.  */
  55.     public POSITION
  56. forw_line(curr_pos)
  57.     POSITION curr_pos;
  58. {
  59.     POSITION new_pos;
  60.     register int c;
  61.     int blankline;
  62.     int endline;
  63.  
  64.     if (curr_pos == NULL_POSITION)
  65.     {
  66.         null_line();
  67.         return (NULL_POSITION);
  68.     }
  69. #if HILITE_SEARCH
  70.     if (hilite_search == OPT_ONPLUS)
  71.         prep_hilite(curr_pos, curr_pos + 3*size_linebuf);
  72. #endif
  73.     if (ch_seek(curr_pos))
  74.     {
  75.         null_line();
  76.         return (NULL_POSITION);
  77.     }
  78.  
  79.     prewind();
  80.     plinenum(curr_pos);
  81.     (void) ch_seek(curr_pos);
  82.  
  83.     c = ch_forw_get();
  84.     if (c == EOI)
  85.     {
  86.         null_line();
  87.         return (NULL_POSITION);
  88.     }
  89.     blankline = (c == '\n' || c == '\r');
  90.  
  91.     for (;;)
  92.     {
  93.         if (ABORT_SIGS())
  94.         {
  95.             null_line();
  96.             return (NULL_POSITION);
  97.         }
  98.         if (c == '\n' || c == EOI)
  99.         {
  100.             /*
  101.              * End of the line.
  102.              */
  103.             new_pos = ch_tell();
  104.             endline = 1;
  105.             break;
  106.         }
  107.  
  108.         /*
  109.          * Append the char to the line and get the next char.
  110.          */
  111.         if (pappend(c, ch_tell()-1))
  112.         {
  113.             /*
  114.              * The char won't fit in the line; the line
  115.              * is too long to print in the screen width.
  116.              * End the line here.
  117.              */
  118.             if (chopline)
  119.             {
  120.                 do
  121.                 {
  122.                     c = ch_forw_get();
  123.                 } while (c != '\n' && c != EOI);
  124.                 new_pos = ch_tell();
  125.                 endline = 1;
  126.             } else
  127.             {
  128.                 new_pos = ch_tell() - 1;
  129.                 endline = 0;
  130.             }
  131.             break;
  132.         }
  133.         c = ch_forw_get();
  134.     }
  135.     pdone(endline);
  136.  
  137.     if (squeeze && blankline)
  138.     {
  139.         /*
  140.          * This line is blank.
  141.          * Skip down to the last contiguous blank line
  142.          * and pretend it is the one which we are returning.
  143.          */
  144.         while ((c = ch_forw_get()) == '\n' || c == '\r')
  145.             if (ABORT_SIGS())
  146.             {
  147.                 null_line();
  148.                 return (NULL_POSITION);
  149.             }
  150.         if (c != EOI)
  151.             (void) ch_back_get();
  152.         new_pos = ch_tell();
  153.     }
  154.  
  155.     return (new_pos);
  156. }
  157.  
  158. /*
  159.  * Get the previous line.
  160.  * A "current" position is passed and a "new" position is returned.
  161.  * The current position is the position of the first character of
  162.  * a line.  The new position is the position of the first character
  163.  * of the PREVIOUS line.  The line obtained is the one starting at new_pos.
  164.  */
  165.     public POSITION
  166. back_line(curr_pos)
  167.     POSITION curr_pos;
  168. {
  169.     POSITION new_pos, begin_new_pos;
  170.     int c;
  171.     int endline;
  172.  
  173.     if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
  174.     {
  175.         null_line();
  176.         return (NULL_POSITION);
  177.     }
  178. #if HILITE_SEARCH
  179.     if (hilite_search == OPT_ONPLUS)
  180.         prep_hilite((curr_pos < 3*size_linebuf) ? 
  181.                 0 : curr_pos - 3*size_linebuf, curr_pos);
  182. #endif
  183.     if (ch_seek(curr_pos-1))
  184.     {
  185.         null_line();
  186.         return (NULL_POSITION);
  187.     }
  188.  
  189.     if (squeeze)
  190.     {
  191.         /*
  192.          * Find out if the "current" line was blank.
  193.          */
  194.         (void) ch_forw_get();    /* Skip the newline */
  195.         c = ch_forw_get();    /* First char of "current" line */
  196.         (void) ch_back_get();    /* Restore our position */
  197.         (void) ch_back_get();
  198.  
  199.         if (c == '\n' || c == '\r')
  200.         {
  201.             /*
  202.              * The "current" line was blank.
  203.              * Skip over any preceding blank lines,
  204.              * since we skipped them in forw_line().
  205.              */
  206.             while ((c = ch_back_get()) == '\n' || c == '\r')
  207.                 if (ABORT_SIGS())
  208.                 {
  209.                     null_line();
  210.                     return (NULL_POSITION);
  211.                 }
  212.             if (c == EOI)
  213.             {
  214.                 null_line();
  215.                 return (NULL_POSITION);
  216.             }
  217.             (void) ch_forw_get();
  218.         }
  219.     }
  220.  
  221.     /*
  222.      * Scan backwards until we hit the beginning of the line.
  223.      */
  224.     for (;;)
  225.     {
  226.         if (ABORT_SIGS())
  227.         {
  228.             null_line();
  229.             return (NULL_POSITION);
  230.         }
  231.         c = ch_back_get();
  232.         if (c == '\n')
  233.         {
  234.             /*
  235.              * This is the newline ending the previous line.
  236.              * We have hit the beginning of the line.
  237.              */
  238.             new_pos = ch_tell() + 1;
  239.             break;
  240.         }
  241.         if (c == EOI)
  242.         {
  243.             /*
  244.              * We have hit the beginning of the file.
  245.              * This must be the first line in the file.
  246.              * This must, of course, be the beginning of the line.
  247.              */
  248.             new_pos = ch_tell();
  249.             break;
  250.         }
  251.     }
  252.  
  253.     /*
  254.      * Now scan forwards from the beginning of this line.
  255.      * We keep discarding "printable lines" (based on screen width)
  256.      * until we reach the curr_pos.
  257.      *
  258.      * {{ This algorithm is pretty inefficient if the lines
  259.      *    are much longer than the screen width, 
  260.      *    but I don't know of any better way. }}
  261.      */
  262.     if (ch_seek(new_pos))
  263.     {
  264.         null_line();
  265.         return (NULL_POSITION);
  266.     }
  267.     endline = 0;
  268.     loop:
  269.     begin_new_pos = new_pos;
  270.     prewind();
  271.     plinenum(new_pos);
  272.     (void) ch_seek(new_pos);
  273.  
  274.     do
  275.     {
  276.         c = ch_forw_get();
  277.         if (c == EOI || ABORT_SIGS())
  278.         {
  279.             null_line();
  280.             return (NULL_POSITION);
  281.         }
  282.         new_pos++;
  283.         if (c == '\n')
  284.         {
  285.             endline = 1;
  286.             break;
  287.         }
  288.         if (pappend(c, ch_tell()-1))
  289.         {
  290.             /*
  291.              * Got a full printable line, but we haven't
  292.              * reached our curr_pos yet.  Discard the line
  293.              * and start a new one.
  294.              */
  295.             if (chopline)
  296.             {
  297.                 endline = 1;
  298.                 break;
  299.             }
  300.             pdone(0);
  301.             (void) ch_back_get();
  302.             new_pos--;
  303.             goto loop;
  304.         }
  305.     } while (new_pos < curr_pos);
  306.  
  307.     pdone(endline);
  308.  
  309.     return (begin_new_pos);
  310. }
  311.